// 引擎管理器（lib/tts_engine_manager.dart）
import 'dart:convert';

import 'package:flutter_deer/mvvm/base_net_provider.dart';
import 'package:flutter_deer/res/constant.dart';
import 'package:flutter_deer/util/print/data/order_type_option.dart';
import 'package:flutter_deer/util/speak/tts_base_engine.dart';
import 'package:flutter_deer/util/speak/tts_engine_default.dart';
import 'package:flutter_deer/util/speak/tts_engine_gb.dart';
import 'package:flutter_deer/util/toast_utils.dart';
import 'package:get/get.dart';
import 'package:sp_util/sp_util.dart';

import 'speak_type_option.dart';

class TtsEngineManager extends BaseNetProvider {
  // 总开关
  final RxBool rxIsOpen = true.obs;

  set isOpenTts(bool value) {
    rxIsOpen.value = value;
    SpUtil.putBool(Constant.optionSwitchSpeak, value);
  }

  // 按客户端播报
  final RxList<String> rxSelectOpenByClient = <String>[].obs;

  set selectOpenTtsByClient(List<String> value) {
    rxSelectOpenByClient.value = value;
    SpUtil.putStringList(Constant.optionSwitchSpeakByClient, value);
  }

  List<BroadcastType> get openTtsByClientSelect {
    final list = <BroadcastType>[];
    for (final element in rxSelectOpenByClient) {
      for (final value in BroadcastType.values) {
        if (value.indexKey == element) {
          list.add(value);
        }
      }
    }
    return list;
  }

  String get openTtsByClientString {
    final list = rxSelectOpenByClient;
    if (list.isEmpty) {
      return '关闭';
    } else if (list.length == BroadcastType.values.length) {
      return '全部';
    } else {
      return '${list.length}/${BroadcastType.values.length}';
    }
  }

  // 按业务播报
  final RxList<String> rxSelectOpenByBusiness = <String>[].obs;

  set selectOpenTtsByBusiness(List<String> value) {
    rxSelectOpenByBusiness.value = value;
    SpUtil.putStringList(Constant.optionSwitchSpeakByBusiness, value);
  }

  List<BusinessTypeSelect> get openTtsByBusinessSelect {
    final list = <BusinessTypeSelect>[];
    for (final element in rxSelectOpenByBusiness) {
      for (final value in BusinessTypeSelect.values) {
        if (value.indexKey == element) {
          list.add(value);
        }
      }
    }
    return list;
  }

  String get openTtsByBusinessString {
    final list = rxSelectOpenByBusiness;
    if (list.isEmpty) {
      return '关闭';
    } else if (list.length == BusinessTypeSelect.values.length) {
      return '全部';
    } else {
      return '${list.length}/${BusinessTypeSelect.values.length}';
    }
  }

  // 按员工播报
  final RxList<String> rxSelectOpenByUserIds = <String>[].obs;

  set selectOpenTtsByEmployee(List<String> value) {
    rxSelectOpenByUserIds.value = value;
    SpUtil.putStringList(Constant.optionSwitchSpeakByEmployee, value);
  }

  // 按枪号播报
  final RxList<String> rxSelectOpenByNzl = <String>[].obs;

  set selectOpenTtsByNzl(List<String> value) {
    rxSelectOpenByNzl.value = value;
    SpUtil.putStringList(Constant.optionSwitchSpeakByGun, value);
  }

  final Map<String, ITtsBaseEngine> _engines = <String, ITtsBaseEngine>{};

  @override
  void onInit() {
    super.onInit();
    rxIsOpen.value = SpUtil.getBool(Constant.optionSwitchSpeak, defValue: true) == true;
    rxSelectOpenByClient.value = SpUtil.getStringList(Constant.optionSwitchSpeakByClient) ?? [];
    rxSelectOpenByUserIds.value = SpUtil.getStringList(Constant.optionSwitchSpeakByEmployee) ?? [];
    rxSelectOpenByBusiness.value = SpUtil.getStringList(Constant.optionSwitchSpeakByBusiness) ?? [];
    rxSelectOpenByNzl.value = SpUtil.getStringList(Constant.optionSwitchSpeakByGun) ?? [];
    initSpeakStyleList();
    registerEngine();
  }

  /// 注册引擎
  void registerEngine() {
    final ttsEngineDefault = TtsEngineDefault();
    _engines['windows'] = ttsEngineDefault;
    ttsEngineDefault.init();

    _engines['jb'] = TtsEngineGbSpeaker();
  }

  /// 切换引擎
  Future<void> switchEngine(
    String name, {
    required Map<String, dynamic> config,
    required Function(dynamic) onError,
    required Function() onComplete,
  }) async {}

  /// 代理方法
  Future<void> speak(String text, {bool? toast = false}) async {
    if (toast == true) {
      Toast.show(text);
    }
    // 判断开关
    if (SpUtil.getBool(Constant.switchSpeakJb, defValue: true) == true) {
      await _engines['jb']?.speak(text);
    }
    if (SpUtil.getBool(Constant.switchSpeakWindows, defValue: true) == true) {
      await _engines['windows']?.speak(text);
    }
  }

  // 语音播报内容风格列表
  final RxList<SpeakStyleData> speakStyleList = <SpeakStyleData>[].obs;

  // 初始化语音播报内容风格列表
  void initSpeakStyleList() {
    speakStyleList.clear();
    final speakStr = SpUtil.getString(Constant.optionSwitchSpeakStyle, defValue: "");

    if (speakStr == null || speakStr.isEmpty) {
      // 如果没有保存的数据，则使用默认值
      for (final element in SpeakTypeEnu.values) {
        speakStyleList.add(SpeakStyleData(
          speakStyle: element.speakStyle,
          speakId: element.speakId,
        ));
      }
      print('初始化语音播报内容风格列表1 ---> ${speakStyleList.length}');
    } else {
      try {
        // 解析保存的数据
        final List<dynamic> jsonList = json.decode(speakStr) as List<dynamic>;
        final list = jsonList
            .map((item) => SpeakStyleData(
                  speakId: item['speakId'] as int,
                  speakStyle: item['speakStyle'] as String,
                  speakContent: item['speakContent'] as String,
                  speakSupply: item['speakSupply'] as String,
                ))
            .toList();

        speakStyleList.addAll(list);

        // 添加新增的类型
        for (final element in SpeakTypeEnu.values) {
          final bool exists = list.any((s) => s.speakId == element.speakId);
          if (!exists) {
            speakStyleList.add(SpeakStyleData(speakStyle: element.speakStyle, speakId: element.speakId));
          }
        }
      } catch (e) {
        // 解析失败时使用默认值
        speakStyleList.clear();
        for (final element in SpeakTypeEnu.values) {
          speakStyleList.add(SpeakStyleData(speakStyle: element.speakStyle, speakId: element.speakId));
        }
      }
    }
  }

  // 保存语音播报内容风格列表
  void saveSpeakStyleList() {
    speakStyleList.refresh();
    final jsonList = speakStyleList.map((e) => e.toJson()).toList();
    final jsonStr = json.encode(jsonList);
    SpUtil.putString(Constant.optionSwitchSpeakStyle, jsonStr);
  }

  // 根据订单类型获取播报内容风格
  SpeakStyleData? getSpeakStyleDataByOrderType(int orderType) {
    if (orderType < OrderTypeOption.h2.typeId) {
      return speakStyleList.firstWhereOrNull((element) => element.speakId == 0);
    }
    if (orderType == OrderTypeOption.recharge.typeId) {
      return speakStyleList.firstWhereOrNull((element) => element.speakId == 1);
    }
    if (orderType == OrderTypeOption.store.typeId || orderType == OrderTypeOption.oilStore.typeId) {
      return speakStyleList.firstWhereOrNull((element) => element.speakId == 2);
    }
    if (orderType == OrderTypeOption.tongFu.typeId) {
      return speakStyleList.firstWhereOrNull((element) => element.speakId == 3);
    }
    return null;
  }

  // 根据订单类型判断是否需要播报
  bool canSpeakByOrderType(int orderType, String logInfo) {
    if (orderType < OrderTypeOption.h2.typeId) {
      if (!rxSelectOpenByBusiness.contains(BusinessTypeSelect.oil.indexKey)) {
        print('限制播报：$orderType 业务不可播报 $logInfo');
        return false;
      }
    }
    if (orderType == OrderTypeOption.recharge.typeId) {
      if (!rxSelectOpenByBusiness.contains(BusinessTypeSelect.recharge.indexKey)) {
        print('限制播报：$orderType 业务不可播报 $logInfo');
        return false;
      }
    }
    if (orderType == OrderTypeOption.store.typeId || orderType == OrderTypeOption.oilStore.typeId) {
      if (!rxSelectOpenByBusiness.contains(BusinessTypeSelect.store.indexKey)) {
        print('限制播报：$orderType 业务不可播报 $logInfo');
        return false;
      }
    }
    if (orderType == OrderTypeOption.tongFu.typeId) {
      if (!rxSelectOpenByBusiness.contains(BusinessTypeSelect.tong.indexKey)) {
        print('限制播报：$orderType 业务不可播报 $logInfo');
        return false;
      }
    }
    return true;
  }
}

// 枚举
enum TtsEngineType {
  defaultEngine,
  gbPrinterEngine,
}

/// 客户端
enum BroadcastType {
  localStore('1', '仅本机'),
  otherStore('2', '非本机'),
  driverMini('3', '小程序等'),
  ;

  final String indexKey;
  final String label;

  const BroadcastType(this.indexKey, this.label);
}

/// 业务 "油品", "便利店", "储值卡充值", "通付", "券核销（只打印本机核销）"
enum BusinessTypeSelect {
  oil('1', '加油'),
  store('2', '便利店'),
  recharge('3', '储值卡充值'),
  tong('4', '通付'),
  coupon('5', '券核销（只打印本机核销）'),
  ;

  final String indexKey;
  final String label;

  const BusinessTypeSelect(this.indexKey, this.label);
}
